1. 前言
本文是 << Spring Cloud微服务实战 >> 学习笔记, 以便自己查阅.
2. 服务治理
随着微服务应用的不断增加,静态配置会越来越难以维护,并且随着业务的不断发展,集群规模,服务位置,服务命名都会发生变化,手动维护的方式极易发生错误或是命名冲突问题.因此需要服务治理框架对微服务实例进行管理,服务治理是微服务架构中最核心的功能和模块,主要用来各个微服务实例的自动化注册和发现.
2.1 服务注册
在服务治理框架中,通常都会有一个服务注册中心.每一个微服务实例向注册中心登记自己提供的服务,将主机,端口号,版本号,通信协议等一些信息告知注册中心.注册中心按服务名分类组织服务清单.
服务注册中心需要以心跳的方式监测服务清单中的服务是否可用,如果不可用,需要将不可用的服务实例进行剔除.
2.2 服务发现
服务间的调用通过向服务名发起请求调用实现.服务调用方在调用提供方的接口时,并不知道提供方的具体地址.服务调用方需要从注册中心获取所有服务的实例清单,才可以实现对具体服务实例的访问.
服务调用方在发起调用时,会以某种策略取出一个具体的服务实例进行服务调用(客户端负载均衡).
在实际的环境中,为了提高性能,并不会采用每次都向服务注册中心获取服务的方式进行服务的调用,并且不同的应用场景在缓存和服务剔除等机制上可以采用不同的实现策略.
3. Netflix Eureka
Spring Cloud Eureka采用Netflix Eureka来实现服务注册与发现,包含客户端和服务端组件.
3.1 Eureka服务端(服务注册中心)
支持高可用配置.
依托于强一致性提供良好的服务实例可用性.
服务注册中心之间可以通过异步模式互相复制各自的状态.
3.2 Eureka客户端
主要用于服务的注册和发现.
客户端可以通过注解和参数配置的方式实现注册与发现.
Eureka客户端向注册中心注册自身提供的服务并周期性地发送心跳来更新它的服务租约.
Eureka客户端从服务端查询当前注册的服务信息并把它们缓存到本地并周期性的刷新服务状态.
3.2.1 关于客户端的说明
客户端其实分为两种, 一种是服务提供方, 一种是服务消费方, 服务提供方需要向注册中心注册自身提供的服务并周期性地发送心跳来更新它的服务租约. 而服务消费方从服务端查询当前注册的服务信息并把它们缓存到本地并周期性的刷新服务状态.
3.3 服务发现与消费
服务消费者的主要目标是发现和消费服务.其中服务发现由Eureka客户端完成,服务消费由Ribbon完成.
4. Eureka详解
4.1 基础结构
服务注册中心: Eureka服务端, 提供服务注册和发现的功能.
服务提供者: 提供服务的应用, 将自己提供的服务注册到Eureka, 供其他应用发现
服务消费者: 消费者从注册中心发现服务列表, 然后调用对应的服务(Ribbon或Feign)
备注: 一般一个应用既是服务提供者也是服务消费者.
4.2 服务治理机制
Eureka服务体系图
4.2.1 服务提供者
4.2.1.1 服务注册
服务提供者会以Rest请求的方式注册到注册中心上,在请求过程中会携带自身的一些元数据信息.注册中心在收到请求后,会将元数据信息保存到一个双层Map结构中,外层的key是服务名称,内层的key是具体的服务实例名称.
eureka.client.register-with-eureka,如果该参数的值等于false,不会进行注册.
4.2.1.2 服务同步
如果两个服务注册在两个不同的注册中心上,两个注册中心互相注册成为服务(集群),此时,当服务提供者向其中一个注册中心发起请求时,该注册中心会将请求准发给集群中的其他注册中心,从而实现注册中心之间的服务同步.
由于服务同步的存在,服务提供者的信息可以在任意一台注册中心上获取.
4.2.1.3 服务续约
在服务注册完成之后,服务提供者需要维护一个心跳来告知注册中心服务实例处于正常运行状态中,防止注册中心将正常的服务实例剔除出注册中心.上述操作就成为服务续约.
4.2.2 服务消费者
4.2.2.1 获取服务
启动服务消费者时,服务消费者会向注册中心发起一个Rest请求,来获取注册中心维护的服务实例清单.但是为了提高性能,注册中心会维护一份只读的服务清单返回给客户端,该缓存的服务清单会每隔30s刷新一次.
eureka.client.fetch-registry,如果该参数被设置为false,无法向注册中心获取服务清单.
eureka.client.registry-fetch-interval-seconds,缓存清单的刷新时间,默认30s.
4.2.2.2 服务调用
服务消费者获得服务清单后,可以根据服务名获取具体服务实例列表(元数据信息),根据自己的策略选择具体的服务实例进行调用.
Eureka有Region和Zone的概念,一个Region中会有多个Zone,每个客户端都需要注册到一个Zone中,所以客户端对应一个Region和一个Zone.在服务进行调用时,优先访问同一个Zone中的服务提供方,若访问不到,再访问其他Zone.
4.2.2.3 服务下线
当服务实例正常关闭时,服务实例会发送一个服务下线的Rest请求给注册中心.注册中心在收到请求后,会将该服务实例的状态置为DOWN,并且将下线时间广播出去.
4.2.3 服务注册中心
4.2.3.1 失效剔除
当服务实例未正常下线时(内存溢出,网络故障),服务注册中心未能收到服务下线的Rest请求.注册中心在启动时会创建一个定时任务,默认每隔一段时间(60s)将当前清单中超时(服务失效时间,默认90s)没有续约的服务进行剔除.
4.2.3.2 自我保护
注册中心在运行期间,会统计心跳失败比例在15分钟内是否低于85%,如果出现低于的情况,注册中心会将当前服务实例的注册信息保护起来,让这些实例不会过期.但是,在保护期时间内,如果实例出现问题,那么服务调用者很容易拿到该实例调用失败,所以服务调用者必须要有容错机制(请求重试,断路由器等).
eureka.server.enable-self-preservation,如果该值设置为false,则不启用自我保护机制,默认值为true
5. 其他
5.1 健康检测
默认情况下,Eureka中各个服务实例的健康检测并不是通过spring-cloud-actuator模块的/actuator/health节点,而是依靠客户端的心跳来保持服务的存活.
默认的客户端心跳方式无法保证客户端提供正常的服务.比如微服务一般会有依赖的外部资源(如数据库,缓存,消息代理等),假如与这些外部资源无法联通,但是客户端心跳依旧存在,这就会导致调用出现问题.
使用spring-boot-actuator模块的/actuator/health端点,只需要两部曲:
在pom.xml文件中引入spring-boot-actuator依赖
在配置文件中加入eureka.client.healthcheck.enabled=true
6. 参考链接
<< Spring Cloud微服务实战 >>
spring-cloud-eureka服务治理